package clang.ir;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * The C-lang graph is not necessarily a tree.
 */
public abstract class Operator extends Node {

    protected Operator() {
        storageClass = StorageClass.INTERNAL_DECLARED;
    }
    protected Node[] child;

    @Override
    public boolean runtimeExpressionIsComposite() {
        return true;
    }

    public void setChild(Node node, int index) {
        child[index] = node;
    }

    public ArrayList<Node> getChildNodes() {
        ArrayList<Node> childNodes = new ArrayList<Node>();
        childNodes.addAll(Arrays.asList(child));
        return childNodes;
    }

    public int childArrayLength() {
        return child.length;
    }

    public Node getChild(int index) {
        return child[index];
    }

    @Override
    public void buildEvaluationIndex(Node parent) {
        if (parent != null) {
            evaluationIndex = parent.getEvaluationIndex() + 1;
        } else {
            evaluationIndex = 0;
        }
        for (int i = 0; i < child.length; i++) {
            if (child[i].getEvaluationIndex() <= evaluationIndex) {
                child[i].buildEvaluationIndex(this);
            }
        }
    }

    /**
     * @param node
     * @param dataflow
     */
    public void removeChild(Node node, Dataflow dataflow) {
        switch (child.length) {
            case 1:
                if (child[0] == node) {
                    dataflow.remove(this);
                }
                break;
            case 2:
                int indexKeep = Integer.MIN_VALUE;
                if (child[0] == node) {
                    indexKeep = 1;
                } else {
                    if (child[1] == node) {
                        indexKeep = 0;
                    }
                }
                if (indexKeep >= 0) {
                    dataflow.replaceChild(this, child[indexKeep]);
                }
                break;
            default:
                throw new RuntimeException("Invalid child count in C-lang operator");
        }
    }

    public boolean hasSuchChild(Node node) {
        for (Node c : child) {
            if (c == node) {
                return true;
            }
        }
        return false;
    }

    public void replaceChild(Node destination, Node source) {
        for (int i = 0; i < child.length; i++) {
            if (child[i] == destination) {
                child[i] = source;
                break;
            }
        }
    }
}
